using System;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using EnvDTE;
using Microsoft.WowAddonStudio.Lua.LanguageService.Tests.WowCommonTestLibrary.Mocks;
using Microsoft.WowAddonStudio.ProjectRefactor;
using NUnit.Framework;

namespace WowProjectPackage.Tests.ProjectRefactor
{
	[TestFixture]
	public class FrameXmlMergerTest : GeneralDTETestBase
	{
		private const string Frame_Xml_Name = "Frame.xml";
		private const string Lua_File_Name = "Frame2.lua";

		private readonly static string currentDir = String.Concat(Environment.CurrentDirectory, @"\Resources");
		private readonly static string testFrameXmlPath = Path.Combine(currentDir, Frame_Xml_Name);
		private readonly static string testLuaPath = Path.Combine(currentDir, Lua_File_Name);

		#region SetUp

		[SetUp]
		public override void SetUp()
		{
			base.SetUp();
			if(!File.Exists(testFrameXmlPath))
			{
				File.Copy(String.Concat(Path.Combine(Environment.CurrentDirectory, @"..\..\Resources\"), Frame_Xml_Name), testFrameXmlPath);
			}
			if (!File.Exists(testLuaPath))
			{
				File.Copy(String.Concat(Path.Combine(Environment.CurrentDirectory, @"..\..\Resources\"), Lua_File_Name), testLuaPath);
			}
		}

		#endregion

		#region TearDown

		[TearDown]
		public override void TearDown()
		{
			base.SetUp();
			((MockDTE)SimpleTestServiceLocator.Get<DTE>()).SetMockDocuments(null);
		}

		#endregion

		#region Tests

		/// <summary>
		/// Test_s the external merger.
		/// </summary>
		[Test(Description = "")]
		public void Test_ExternalMerger()
		{
			var merger = new FrameXmlFileMerger(testFrameXmlPath);
			merger.MergeFrameName(testFrameXmlPath, testLuaPath);
			CheckValue(Lua_File_Name);
		}

		[Test(Description = "")]
		public void Test_DocumentMerger()
		{
			InitializeMockObjects(GetSource(Path.Combine(currentDir, Frame_Xml_Name)));

			var props = ((MockProperties)SimpleTestServiceLocator.Get<ProjectItem>().Properties);
			if (!props.ContainsKey("FullPath"))
				props.Add("FullPath", CreateMockProperty(props, "FullPath", Path.Combine(currentDir, Frame_Xml_Name)));

			var docs = new MockDocuments(SimpleTestServiceLocator.Get<DTE>(),
				((MockProjectItem)SimpleTestServiceLocator.Get<ProjectItem>()).Object.ToString(),
				new[] { SimpleTestServiceLocator.Get<ProjectItem>().Document });

			((MockDTE)SimpleTestServiceLocator.Get<DTE>()).SetMockDocuments(docs);

			var textDocument = (TextDocument) DTE.ActiveDocument.Object("TextDocument");
			var merger = new FrameXmlDocumentMerger(testFrameXmlPath, textDocument);

			//Merge
			merger.MergeFrameName(testFrameXmlPath, testLuaPath);
		}

		[Test(Description = "")]
		[ExpectedException(typeof(ArgumentException	))]
		public void Test_BaseClassInitFailedTest1()
		{
			var merger = new FrameXmlFileMerger(string.Empty);
			merger.Merge("xml");
		}


		[Test(Description = "")]
		[ExpectedException(typeof(FileNotFoundException))]
		public void Test_BaseClassInitFailedTest2()
		{
			var merger = new FrameXmlFileMerger("valami.xml");
			merger.Merge("xml");
		}

		[Test(Description = "")]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Test_BaseClassInitFailedTest3()
		{
			var merger = new FrameXmlFileMerger(string.Empty);
			merger.MergeFrameName(testFrameXmlPath, string.Empty);
		}

		[Test(Description = "")]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Test_BaseClassInitFailedTest4()
		{
			var merger = new FrameXmlFileMerger(string.Empty);
			merger.MergeFrameName(string.Empty, Lua_File_Name);
		}

		[Test(Description = "")]
		[ExpectedException(typeof(FileNotFoundException))]
		public void Test_BaseClassInitFailedTest5()
		{
			var merger = new FrameXmlFileMerger(string.Empty);
			merger.MergeFrameName("valami.xml", Lua_File_Name);
		}

		[Test(Description = "")]
		[ExpectedException(typeof(FileNotFoundException))]
		public void Test_BaseClassInitFailedTest6()
		{
			var merger = new FrameXmlFileMerger(string.Empty);
			merger.MergeFrameName(testFrameXmlPath, "valami.lua");
		}

		/// <summary>
		/// Checks the value.
		/// </summary>
		private static void CheckValue(string name)
		{
			if (File.Exists(Path.Combine(currentDir, Frame_Xml_Name)))
			{
				bool result = false;
				using (Stream stream = File.OpenRead(Path.Combine(currentDir, Frame_Xml_Name)))
				using (var streamReader = new StreamReader(stream))
				{
					var sourceReader = new StringReader(streamReader.ReadToEnd());
					using (XmlReader reader = XmlReader.Create(sourceReader))
					{
						XElement root = XElement.Load(reader);
						var namespaceManager = new XmlNamespaceManager(reader.NameTable);
						namespaceManager.AddNamespace("ans", FrameXmlMergerFactory.BlizzardNamespace);
						foreach (var scriptElement in root.XPathSelectElements("//ans:Script", namespaceManager))
						{
							// Get the filename of the reference script file
							XAttribute fileAttribute = scriptElement.Attribute("file");
							Assert.IsNotNull(fileAttribute);
							Assert.AreEqual(name, fileAttribute.Value);
							result = true;
						}
					}
				}

				Assert.IsTrue(result);
			}
			else
			{
				throw new FileNotFoundException("Test file not found!", Path.Combine(currentDir, Frame_Xml_Name));
			}
		}

		#endregion
	}
}